// package com.qqt.csr.web.service;
//
// import cn.hutool.core.date.DatePattern;
// import cn.hutool.core.date.DateUtil;
// import com.alibaba.fastjson2.JSONObject;
// import com.google.common.base.Stopwatch;
// import com.google.common.collect.Lists;
// import com.google.common.collect.Maps;
// import com.qqt.csr.common.acl.aics.AICustomerServiceClient;
// import com.qqt.csr.common.acl.aics.resp.ChannelInfoDTO;
// import com.qqt.csr.common.acl.aics.resp.CsMemberInfoDTO;
// import com.qqt.csr.common.exception.BaseException;
// import com.qqt.csr.common.exception.StatusCode;
// import com.qqt.csr.common.utils.CacheKeyUtil;
// import com.qqt.csr.common.utils.JsonUtil;
// import com.qqt.csr.common.utils.ServiceAssert;
// import com.qqt.csr.im.dto.BindDTO;
// import com.qqt.csr.im.dto.BindResultDTO;
// import com.qqt.csr.im.dto.ConversationDTO;
// import com.qqt.csr.im.dto.SendSystemMessageDTO;
// import com.qqt.csr.im.entity.Account;
// import com.qqt.csr.im.entity.Conversation;
// import com.qqt.csr.im.entity.RoomMember;
// import com.qqt.csr.im.enums.ConversationStateEnum;
// import com.qqt.csr.im.enums.OnlineEnum;
// import com.qqt.csr.im.service.AccountService;
// import com.qqt.csr.im.service.RoomMemberService;
// import com.qqt.csr.im.service.mongo.ConversationService;
// import com.qqt.csr.im.service.mongo.MessageService;
// import com.qqt.csr.route.service.RouteTaskService;
// import com.qqt.csr.web.dto.member.CustomerServiceInfoDTO;
// import com.qqt.csr.web.dto.member.VisitorInfoDTO;
// import com.qqt.csr.web.entity.SkillSet;
// import com.qqt.csr.web.entity.SkillSetConfig;
// import com.qqt.csr.web.vo.req.BindingCsReqVO;
// import com.qqt.csr.web.vo.req.ClosingConversationReqVO;
// import com.qqt.csr.web.vo.resp.VisitorConversationInfoRespVo;
// import lombok.extern.slf4j.Slf4j;
// import org.apache.commons.collections.CollectionUtils;
// import org.apache.commons.lang3.StringUtils;
// import org.redisson.api.RedissonClient;
// import org.springframework.beans.factory.annotation.Autowired;
// import org.springframework.beans.factory.annotation.Value;
// import org.springframework.stereotype.Service;
//
// import java.time.Duration;
// import java.util.*;
// import java.util.concurrent.TimeUnit;
// import java.util.concurrent.atomic.AtomicLong;
// import java.util.stream.Collectors;
//
// @Slf4j
// // @Service
// public class CsWorkbenchService {
//     @Value("${csr.workbench.access.defaultLimit:0}")
//     private int csWorkbenchAccessDefaultLimit;
//     @Autowired
//     private AICustomerServiceClient aiCustomerServiceClient;
//     @Autowired
//     private SkillSetService skillSetService;
//     @Autowired
//     private SkillSetMemberService skillSetMemberService;
//     @Autowired
//     private AccountService accountService;
//     @Autowired
//     private ConversationService conversationService;
//     @Autowired
//     private SkillSetConfigService skillSetConfigService;
//     @Autowired
//     private MessageService messageService;
//     @Autowired
//     private ChatTimeJobService chatTimeJobService;
//     @Autowired
//     private RoomMemberService roomMemberService;
//     @Autowired
//     private RouteCsService routeCsService;
//     @Autowired
//     private RedissonClient redissonClient;
//     @Autowired
//     private MqProducerService mqProducerService;
//
//     /**
//      * 用户接入在线客服
//      *
//      * @param req
//      * @return
//      */
//     @Deprecated
//     public VisitorConversationInfoRespVo accessCs(BindingCsReqVO req, String tenantId) {
//         // 通过渠道获取绑定的技能组相关信息
//         ChannelInfoDTO channelInfo = getChannelInfo(req.getChannelId());
//
//         SkillSet skillSet = getSkillSet(channelInfo.getSkillSetId(), tenantId);
//         SkillSetConfig skillSetConfig = getSkillSetConfig(skillSet);
//
//         // 访客
//         VisitorInfoDTO visitorInfo = VisitorInfoDTO.of(req.getChannelUserId(), channelInfo);
//         visitorInfo.bindImAccount(accountService.getByAccountUserId(visitorInfo.buildUserImUserId()));
//         ServiceAssert.notNull(visitorInfo.getAccount(), StatusCode.Common.NOT_EXIST.getCode(), "非法访客！");
//
//         // 判断下当前访客是否已经有进行中会话，如果有，则直接返回，否则创建新会话
//         VisitorConversationInfoRespVo existConversation = queryConversationIfExist(visitorInfo, channelInfo, skillSetConfig);
//         if (existConversation != null) {
//             return existConversation;
//         }
//
//         // 路由匹配在线客服
//         List<CustomerServiceInfoDTO> onlineCsList = getOnlineSkillSetMemeberList(channelInfo, skillSet, skillSetConfig);
//         CustomerServiceInfoDTO routeOnlineCs = routeCsService.route(skillSetConfig, onlineCsList);
//         if (routeOnlineCs == null) {
//             // 无客服在线
//             return VisitorConversationInfoRespVo.buildNotSeatCs(skillSetConfig);
//         }
//
//         // 创建新会话
//         BindResultDTO bindResult = createConversation(channelInfo, visitorInfo, routeOnlineCs, tenantId);
//         if (bindResult == null) {
//             // 绑定会话失败，返回无客服在线
//             log.info("绑定会话失败，返回无客服在线");
//             routeCsService.release(routeOnlineCs.getId(), 1);
//             return VisitorConversationInfoRespVo.buildNotSeatCs(skillSetConfig);
//         }
//
//         try {
//             // 通知客服工作台，新会话创建通知
//             pushNewConversationEventNotify(bindResult);
//             // 创建会话定时监视任务
//             chatTimeJobService.createMonitorJob(skillSetConfig, visitorInfo, routeOnlineCs, bindResult.getConversation().getId());
//             // 推送系统消息到访客和客服工作台
//             pushCreateConversationSystemMsg(bindResult.getRecipient(), bindResult.getInitiator(), bindResult.getConversation(), skillSetConfig);
//             // 记录访客今日转人工次数
//             recordVisitorAccessCsCount(bindResult.getInitiator().getId());
//         } catch (Exception e) {
//             log.error("创建会话成功后，后续逻辑异常！会话id：{}", bindResult.getConversation().getId(), e);
//         }
//
//         return VisitorConversationInfoRespVo.buildBoundConversationSuccess(bindResult, routeOnlineCs, channelInfo, skillSetConfig);
//     }
//
//     /**
//      * 访客获取已存在未结束的会话
//      *
//      * @param req
//      * @param tenantId
//      * @return
//      */
//     public VisitorConversationInfoRespVo getUnClosedConversation(BindingCsReqVO req, String tenantId) {
//         // 通过渠道获取绑定的技能组相关信息
//         ChannelInfoDTO channelInfo = getChannelInfo(req.getChannelId());
//
//         SkillSet skillSet = getSkillSet(channelInfo.getSkillSetId(), tenantId);
//         SkillSetConfig skillSetConfig = getSkillSetConfig(skillSet);
//
//         // 访客
//         VisitorInfoDTO visitorInfo = VisitorInfoDTO.of(req.getChannelUserId(), channelInfo);
//         visitorInfo.bindImAccount(accountService.getByAccountUserId(visitorInfo.buildUserImUserId()));
//         ServiceAssert.notNull(visitorInfo.getAccount(), StatusCode.Common.NOT_EXIST.getCode(), "非法访客！");
//
//         // 判断下当前访客是否已经有进行中会话，如果有，则直接返回，否则创建新会话
//         return queryConversationIfExist(visitorInfo, channelInfo, skillSet, skillSetConfig);
//     }
//
//
//     /**
//      * 结束会话
//      *
//      * @param req
//      */
//     public void closeConversation(ClosingConversationReqVO req, Long csId) {
//         Conversation conversation = conversationService.getById(req.getConversationId());
//         if (conversation == null || ConversationStateEnum.END.equals(conversation.getState())) {
//             return;
//         }
//
//         // im账户信息
//         List<RoomMember> roomMemberList = roomMemberService.queryMemberListBy(Long.parseLong(conversation.getRoomId()));
//         List<Long> accountIdList = roomMemberList.stream().map(RoomMember::getAccountId).distinct().collect(Collectors.toList());
//         Map<Long, Account> accountMap = accountService.getMapByIds(accountIdList);
//
//         // 客服
//         String csImUserId = CustomerServiceInfoDTO.buildCsImUserId(csId);
//         Account csAccount = accountMap.values().stream().filter(a -> a.getAccountUserId().equals(csImUserId)).findFirst().orElse(null);
//         ServiceAssert.notNull(csAccount, StatusCode.Common.ILLEGAL.getCode(), "非当前会话处理人，关闭失败！");
//
//         // 访客
//         Account vistorAccount = accountMap.get(Long.parseLong(conversation.getInitiatorId()));
//
//         // 结束会话
//         conversationService.end(req.getConversationId());
//         // 释放客服进线被占用的访客名额
//         routeCsService.release(csId, 1);
//         // 推送系统消息结束会话提示
//         pushClosedConversationSystemMsg(conversation, vistorAccount, csAccount);
//         // 推送会话结束通知到客服工作台
//         conversationService.pushCloseConversationEvent(csAccount, conversation);
//         // 发送会话归档事件
//         mqProducerService.sendConversationArchiveEvent(Lists.newArrayList(conversation.getId()));
//     }
//
//     /**
//      * 结束客服所有会话，并推送会话结束提醒
//      *
//      * @param csId
//      */
//     public void closeAllConversation(Long csId) {
//         String csImUserId = CustomerServiceInfoDTO.buildCsImUserId(csId);
//         List<ConversationDTO> conversationList = conversationService.queryConversationListBy(csImUserId, ConversationStateEnum.NORMAL, 0);
//         if (CollectionUtils.isEmpty(conversationList)) {
//             return;
//         }
//
//         Account csAccount = conversationList.get(0).getRoomMemberList().stream()
//                 .filter(rm -> rm.getAccountUserId().equals(csImUserId))
//                 .findFirst().orElse(null);
//         if (csAccount == null) {
//             return;
//         }
//
//         List<String> conversatoinIdList = conversationList.stream().map(ConversationDTO::getId).collect(Collectors.toList());
//         // 结束会话
//         conversationService.end(conversatoinIdList);
//         // 释放客服进线被占用的访客名额
//         routeCsService.release(csId, conversationList.size());
//         // 推送系统消息结束会话提示
//         pushClosedConversationSystemMsg(conversationList);
//         // 推送会话结束通知到客服工作台
//         conversationService.pushCloseConversationEvent(csAccount, conversationList);
//         // 发送会话归档事件
//         mqProducerService.sendConversationArchiveEvent(conversatoinIdList);
//     }
//
//     /**
//      * 获取访客今日转人工次数
//      *
//      * @param visitorImAccountId
//      * @return
//      */
//     public long getVisitorAccessCsCount(Long visitorImAccountId) {
//         String redisKey = String.format(CacheKeyUtil.SkillSet.VISITOR_ACCESS_CS_COUNT, visitorImAccountId);
//         return redissonClient.getAtomicLong(redisKey).get();
//     }
//
//     /**
//      * 查询当前访客已经有进行中的会话
//      *
//      * @param visitorInfo
//      * @return
//      */
//     private VisitorConversationInfoRespVo queryConversationIfExist(VisitorInfoDTO visitorInfo, ChannelInfoDTO channelInfo, SkillSetConfig skillSetConfig) {
//         List<ConversationDTO> conversationDTOList = conversationService.queryConversationListBy(visitorInfo.getAccount(), ConversationStateEnum.NORMAL, 1);
//         if (CollectionUtils.isEmpty(conversationDTOList)) {
//             return null;
//         }
//         ConversationDTO existConversation = conversationDTOList.get(0);
//         AtomicLong csId = new AtomicLong();
//         Account csAccount = existConversation.getRoomMemberList().stream()
//                 .filter(rm -> StringUtils.isNotBlank(rm.getExt()))
//                 .filter(rm -> {
//                     JSONObject ext = JsonUtil.toObject(rm.getExt(), JSONObject.class);
//                     if (ext == null || !"1".equals(ext.getString("userType"))) {
//                         return false;
//                     }
//                     csId.set(ext.getLong("csId"));
//                     return true;
//                 }).findFirst().orElse(null);
//         if (csAccount == null) {
//             return null;
//         }
//
//         List<CsMemberInfoDTO> csMemberInfoDtoList = aiCustomerServiceClient.getNormalListBy(Lists.newArrayList(csId.get()));
//         if (CollectionUtils.isEmpty(csMemberInfoDtoList)) {
//             // 客服账号被冻结
//             // 结束会话
//             conversationService.end(existConversation.getId());
//             // 释放客服进线被占用的访客名额
//             routeCsService.release(csId.get(), 1);
//             // 发送会话归档事件
//             mqProducerService.sendConversationArchiveEvent(Lists.newArrayList(existConversation.getId()));
//             return null;
//         }
//         return VisitorConversationInfoRespVo.buildBoundConversationSuccess(existConversation, csAccount, csMemberInfoDtoList.get(0), channelInfo, skillSetConfig);
//     }
//
//
//     /**
//      * 获取渠道信息
//      *
//      * @param channelId
//      * @return
//      */
//     private ChannelInfoDTO getChannelInfo(String channelId) {
//         ChannelInfoDTO channelInfoDto = aiCustomerServiceClient.queryChannelInfo(channelId);
//         ServiceAssert.notNull(channelInfoDto, StatusCode.Common.NULL_ERROR.getCode(), "渠道未配置");
//         ServiceAssert.isTrue(channelInfoDto.getSkillSetId() != null && channelInfoDto.getSkillSetId() > 0, StatusCode.Common.NULL_ERROR.getCode(), "渠道未绑定技能组");
//         return channelInfoDto;
//     }
//
//     /**
//      * 获取技能组信息
//      *
//      * @param skillSetId
//      * @return
//      */
//     private SkillSet getSkillSet(Long skillSetId, String tenantId) {
//         SkillSet skillSet = skillSetService.queryById(skillSetId, tenantId);
//         ServiceAssert.notNull(skillSet, StatusCode.Common.NOT_EXIST.getCode(), "渠道绑定技能组已失效");
//         return skillSet;
//     }
//
//     /**
//      * 获取技能组配置信息
//      *
//      * @param skillSet
//      * @return
//      */
//     private SkillSetConfig getSkillSetConfig(SkillSet skillSet) {
//         SkillSetConfig skillSetConfig = skillSetConfigService.queryBySkillSetId(skillSet.getId());
//         ServiceAssert.notNull(skillSetConfig, StatusCode.Common.NOT_EXIST.getCode(), "渠道绑定的技能组未进行技能组配置");
//         return skillSetConfig;
//     }
//
//     /**
//      * 获取技能组在线客服列表
//      *
//      * @param channelInfo
//      * @param skillSet
//      * @param skillSetConfig
//      * @return
//      */
//     private List<CustomerServiceInfoDTO> getOnlineSkillSetMemeberList(ChannelInfoDTO channelInfo, SkillSet skillSet, SkillSetConfig skillSetConfig) {
//         List<Long> csIdList = skillSetMemberService.getReadyNormalCsIdList(skillSet.getId());
//         List<CsMemberInfoDTO> csMemberInfoDtoList = aiCustomerServiceClient.getNormalListBy(csIdList);
//         if (CollectionUtils.isEmpty(csMemberInfoDtoList)) {
//             return Lists.newArrayList();
//         }
//
//         List<String> csImAccountUserIdList = csMemberInfoDtoList.stream()
//                 .filter(m -> m.getReceptionLimit() != null && m.getReceptionLimit() > 0)
//                 .map(CsMemberInfoDTO::getUserId)
//                 .map(CustomerServiceInfoDTO::buildCsImUserId)
//                 .collect(Collectors.toList());
//         log.info("获取im在线用户信息请求参数：{}", csImAccountUserIdList);
//         Stopwatch stopwatch = Stopwatch.createStarted();
//         Map<String, Account> imAccountMap = accountService.getMapByUserIds(csImAccountUserIdList);
//         stopwatch.stop();
//         log.info("获取im在线用户信息响应参数：{}，耗时：{}ms", JsonUtil.toJson(imAccountMap), stopwatch.elapsed(TimeUnit.MILLISECONDS));
//
//         return csMemberInfoDtoList.stream()
//                 .map(csMemberInfoDto -> {
//                     CustomerServiceInfoDTO csInfoDto = new CustomerServiceInfoDTO();
//                     csInfoDto.setId(csMemberInfoDto.getUserId());
//                     if (channelInfo.isSkillSetAppearanceType()) {
//                         csInfoDto.setName(skillSetConfig.getCsNickname());
//                         csInfoDto.setHeadImg(skillSetConfig.getCsHeadImg());
//                     } else if (channelInfo.isCsAppearanceType()) {
//                         csInfoDto.setName(csMemberInfoDto.getNickName());
//                         csInfoDto.setHeadImg(csMemberInfoDto.getHeadImg());
//                     } else {
//                         csInfoDto.setName(StringUtils.EMPTY);
//                         csInfoDto.setHeadImg(StringUtils.EMPTY);
//                     }
//                     csInfoDto.setSkillSetId(skillSet.getId());
//                     csInfoDto.setSkillSetName(skillSet.getName());
//                     csInfoDto.setImAccount(imAccountMap.get(csInfoDto.buildCsImUserId()));
//                     csInfoDto.setReceptionLimit(Optional.ofNullable(csMemberInfoDto.getReceptionLimit()).orElse(csWorkbenchAccessDefaultLimit));
//                     return csInfoDto;
//                 })
//                 .filter(csInfoDto -> csInfoDto.getImAccount() != null && csInfoDto.getReceptionLimit() > 0)
//                 .filter(csInfoDto -> OnlineEnum.ONLINE.getCode().equals(csInfoDto.getImAccount().getType()))
//                 .collect(Collectors.toList());
//     }
//
//     /**
//      * 创建访客与客服的新会话
//      *
//      * @param visitorInfo   访客
//      * @param routeOnlineCs 在线客服
//      * @return
//      */
//     private BindResultDTO createConversation(ChannelInfoDTO channelInfo, VisitorInfoDTO visitorInfo, CustomerServiceInfoDTO routeOnlineCs, String tenantId) {
//         Map<String, String> roomExt = Maps.newHashMap();
//         roomExt.put("tenantId", tenantId);
//         roomExt.put("skillSetId", String.valueOf(routeOnlineCs.getSkillSetId()));
//         roomExt.put("skillSetName", routeOnlineCs.getSkillSetName());
//         roomExt.put("channelId", visitorInfo.getChannelId());
//         roomExt.put("channelName", visitorInfo.getChannelName());
//         Optional.ofNullable(channelInfo.getAppearanceType()).ifPresent(appearanceType -> {
//             roomExt.put("appearanceType", appearanceType.toString());
//         });
//         String roomExtStr = JsonUtil.toJson(roomExt);
//
//         try {
//             BindDTO imBindDto = BindDTO.builder()
//                     .initiator(visitorInfo.getAccount())
//                     .recipient(routeOnlineCs.getImAccount())
//                     .roomExt(roomExtStr)
//                     .conversationExt(roomExtStr)
//                     .build();
//             log.info("绑定会话参数：{}", imBindDto);
//             Stopwatch stopwatch = Stopwatch.createStarted();
//             BindResultDTO imBoundResult = conversationService.create(imBindDto);
//             stopwatch.stop();
//             log.info("绑定会话结果：{}，耗时：{}ms", imBoundResult, stopwatch.elapsed(TimeUnit.MILLISECONDS));
//             return imBoundResult;
//         } catch (BaseException e) {
//             log.warn("无对应的im账户信息initiatorId:{},recipientId:{}", visitorInfo.buildUserImUserId(), routeOnlineCs.buildCsImUserId());
//             return null;
//         } catch (Exception e) {
//             log.error("创建会话异常！initiatorId:{},recipientId:{}", visitorInfo.buildUserImUserId(), routeOnlineCs.buildCsImUserId(), e);
//             return null;
//         }
//     }
//
//     /**
//      * 推送新会话通知到客服工作台
//      *
//      * @param bindResult
//      */
//     private void pushNewConversationEventNotify(BindResultDTO bindResult) {
//         Map<Long, Account> accountMap = Maps.newHashMap();
//         accountMap.put(bindResult.getInitiator().getId(), bindResult.getInitiator());
//         accountMap.put(bindResult.getRecipient().getId(), bindResult.getRecipient());
//         conversationService.pushNewConversationEvent(bindResult.getRecipient(), bindResult.getRoom(), accountMap);
//     }
//
//     /**
//      * 推送会话接入系统消息到客服工作台
//      *
//      * @param recipient
//      */
//     private void pushCreateConversationSystemMsg(Account recipient, Account initiator, Conversation conversation, SkillSetConfig skillSetConfig) {
//         // 与前端约定，系统消息扩展字段带有 systemMsgType=2 的，表示会话接入
//         JSONObject systemMsgExt = new JSONObject();
//         systemMsgExt.put("systemMsgType", "2");
//         String systemMsgExtStr = systemMsgExt.toJSONString();
//
//         String todayStr = DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN) + "&nbsp;&nbsp;&nbsp;";
//
//         List<SendSystemMessageDTO> sendSystemMessageList = new ArrayList<>();
//         sendSystemMessageList.add(SendSystemMessageDTO.of(initiator.getAccountUserId(), conversation.getId(), skillSetConfig.getGreetingsTip(), systemMsgExtStr, conversation.getRoomId()));
//         sendSystemMessageList.add(SendSystemMessageDTO.of(recipient.getAccountUserId(), conversation.getId(), todayStr + initiator.getAccountName() + "接入会话，请及时接待", systemMsgExtStr, conversation.getRoomId()));
//
//         Map<String, Account> aMap = new HashMap<>();
//         aMap.put(initiator.getAccountUserId(), initiator);
//         aMap.put(recipient.getAccountUserId(), recipient);
//         messageService.sendSystemMsg(sendSystemMessageList, aMap);
//     }
//
//     private void pushClosedConversationSystemMsg(Conversation conversation, Account visitorAccount, Account csAccount) {
//         JSONObject conversationExt = Optional.ofNullable(JsonUtil.toObject(conversation.getExt(), JSONObject.class)).orElseGet(JSONObject::new);
//         SkillSetConfig skillSetConfig = skillSetConfigService.queryBySkillSetId(conversationExt.getLong("skillSetId"));
//
//         String todayStr = DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN) + "&nbsp;&nbsp;&nbsp;";
//         String endTip = todayStr + Optional.ofNullable(skillSetConfig).map(SkillSetConfig::getEndSessionTip).orElse(StringUtils.EMPTY);
//         // 与前端约定，系统消息扩展字段带有 systemMsgType=1 的，表示会话结束
//         JSONObject systemMsgExt = new JSONObject();
//         systemMsgExt.put("systemMsgType", "1");
//         String systemMsgExtStr = systemMsgExt.toJSONString();
//
//         List<SendSystemMessageDTO> sendSystemMessageList = new ArrayList<>();
//         Map<String, Account> accountMap = new HashMap<>();
//         if (visitorAccount != null) {
//             sendSystemMessageList.add(SendSystemMessageDTO.of(visitorAccount.getAccountUserId(), conversation.getId(), endTip, systemMsgExtStr, conversation.getRoomId()));
//             accountMap.put(visitorAccount.getAccountUserId(), visitorAccount);
//         }
//         if (csAccount != null) {
//             sendSystemMessageList.add(SendSystemMessageDTO.of(csAccount.getAccountUserId(), conversation.getId(), endTip, systemMsgExtStr, conversation.getRoomId()));
//             accountMap.put(csAccount.getAccountUserId(), csAccount);
//         }
//
//         messageService.sendSystemMsg(sendSystemMessageList, accountMap);
//     }
//
//     private void pushClosedConversationSystemMsg(List<ConversationDTO> conversationList) {
//         // 查询技能组配置，获取结束提示信息
//         Map<String, Long> conversationSkillConfigMap = conversationList.stream()
//                 .map(c -> {
//                     JSONObject ext = JsonUtil.toObject(c.getExt(), JSONObject.class);
//                     if (ext == null) {
//                         return null;
//                     }
//                     ext.put("cId", c.getId());
//                     return ext;
//                 }).filter(Objects::nonNull)
//                 .collect(Collectors.toMap(ext -> ext.getString("cId"), v -> v.getLong("skillSetId"), (o, n) -> o));
//         Map<Long, SkillSetConfig> skillSetConfigMap = skillSetConfigService.queryBySkillSetId(conversationSkillConfigMap.values().stream().distinct().collect(Collectors.toList()));
//
//         String todayStr = DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN) + "&nbsp;&nbsp;&nbsp;";
//
//         // 与前端约定，系统消息扩展字段带有 systemMsgType=1 的，表示会话结束
//         JSONObject systemMsgExt = new JSONObject();
//         systemMsgExt.put("systemMsgType", "1");
//         String systemMsgExtStr = systemMsgExt.toJSONString();
//
//         Map<String, Account> accountMap = new HashMap<>();
//         List<SendSystemMessageDTO> sendSystemMessageList = new ArrayList<>();
//         conversationList.forEach(conversationVO -> {
//             String endTip = Optional.ofNullable(conversationSkillConfigMap.get(conversationVO.getId()))
//                     .map(skillSetConfigMap::get)
//                     .map(SkillSetConfig::getEndSessionTip)
//                     .map(tip -> todayStr + tip)
//                     .orElse(StringUtils.EMPTY);
//
//             conversationVO.getRoomMemberList().forEach(account -> {
//                 sendSystemMessageList.add(SendSystemMessageDTO.of(account.getAccountUserId(), conversationVO.getId(), endTip, systemMsgExtStr, conversationVO.getRoomId().toString()));
//                 accountMap.put(account.getAccountUserId(), account);
//             });
//         });
//         messageService.sendSystemMsg(sendSystemMessageList, accountMap);
//     }
//
//     /**
//      * 记录访客今日转人工次数
//      *
//      * @param visitorImAccountId
//      */
//     private void recordVisitorAccessCsCount(Long visitorImAccountId) {
//         String redisKey = String.format(CacheKeyUtil.SkillSet.VISITOR_ACCESS_CS_COUNT, visitorImAccountId);
//         redissonClient.getAtomicLong(redisKey).incrementAndGet();
//         Date currentTime = new Date();
//         redissonClient.getAtomicLong(redisKey).expire(Duration.ofMillis(DateUtil.endOfDay(currentTime).getTime() - currentTime.getTime()));
//     }
// }
